﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using CarbonExchange.AmeeQuery;
using CarbonExchange.Dal;

namespace CarbonExchange.Bll
{
    public class EmailRestrictionFactory : FactoryBase<EmailRestriction>
    {
        public EmailRestrictionFactory() : base() { }

        public EmailRestrictionFactory(IAmeeCommand ameeCommand) : base(ameeCommand) { }

        public EmailRestrictionFactory(Context dalContext) : base(dalContext) { }

        public EmailRestrictionFactory(IAmeeCommand ameeCommand, Context dalContext) : base(ameeCommand, dalContext) { }

        protected override object GetDataItemForUpdate(EmailRestriction item)
        {
            return item.Convert(DalContext);
        }

        protected override void PopulateDataChanges(EmailRestriction item, object dataItem)
        {
            var tmp = dataItem as Dal.EmailRestriction;
            if (item.Id == 0)
            {
                item.Id = tmp.Id;
                item.Created = tmp.Created;
            }
        }

        protected override void MarkItemForDeletion(EmailRestriction item)
        {
            if (item.Id > 0)
            {
                var dataItem = item.Convert(DalContext);
                dataItem.Deleted = true;
            }
        }

        private IQueryable<Dal.EmailRestriction> GetSelection()
        {
            return base.DalContext.EmailRestrictions.Where(x => !x.Deleted).OrderBy(x => x.EmailFilter);
        }

        public IQueryable<EmailRestriction> GetAllBySiteId(int siteId)
        {
            return GetSelection().Where(x => x.SiteId == siteId).Convert();
        }

        public IQueryable<EmailRestriction> GetAllByUserId(int userId)
        {
            var tmp = GetSelection()
                    .Join(DalContext.Users, x => x.SiteId, y => y.SiteId, (x, y) => new { Restriction = x, User = y })
                    .Where(x => x.User.Id == userId).Select(x => x.Restriction).Convert();
            return tmp;
        }

        public EmailRestriction GetById(int id)
        {
            return GetSelection().Where(x => x.Id == id).SingleOrDefault().Convert();
        }

        public bool ValidateEmail(string emailAddress, IQueryable<EmailRestriction> items)
        {
            bool foundAllowed = false;
            foreach (EmailRestriction item in items)
            {
                var tmp = item.ValidateEmail(emailAddress);
                if (tmp == EmailRestriction.ValidationResult.Allowed)
                    foundAllowed = true;
                else if(tmp == EmailRestriction.ValidationResult.Refused)
                    return false;
            }
            return foundAllowed;
        }

        protected override void Validate(IQueryable<EmailRestriction> items, CarbonExchange.Bll.Exceptions.ValidationException exp)
        {
            items.Validate(exp, DalContext);
        }
    }

    internal static class EmailRestrictionFactoryConverter
    {
        internal static IQueryable<EmailRestriction> Convert(this IQueryable<Dal.EmailRestriction> source)
        {
            return source.Select(x => ConvertItem(x));
        }

        internal static EmailRestriction Convert(this Dal.EmailRestriction source)
        {
            return ConvertItem(source);
        }

        internal static EmailRestriction ConvertItem(Dal.EmailRestriction item)
        {
            if (item != null)
            {
                return new EmailRestriction()
                {
                    Id = item.Id,
                    EmailFilter = item.EmailFilter,
                    SiteId = item.SiteId,
                    Access = item.Access,
                    Created = DateTime.SpecifyKind(item.Created, DateTimeKind.Utc).ToLocalTime()
                };
            }
            else
            {
                return null;
            }
        }

        internal static Dal.EmailRestriction Convert(this EmailRestriction source, Dal.Context context)
        {
            Dal.EmailRestriction dataItem = null;
            if (source.Id > 0)
            {
                dataItem = context.EmailRestrictions.Where(x => x.Id == source.Id).Single();
            }
            else
            {
                dataItem = new CarbonExchange.Dal.EmailRestriction();
                context.EmailRestrictions.InsertOnSubmit(dataItem);
                dataItem.Created = DateTime.Now.ToUniversalTime();
                dataItem.SiteId = source.SiteId;
            }
            dataItem.EmailFilter = source.EmailFilter;
            dataItem.Access = source.Access;
            return dataItem;
        }

        internal static void Validate(this IQueryable<EmailRestriction> source, Exceptions.ValidationException e, Dal.Context context)
        {
            foreach(EmailRestriction item in source)
            {
                item.Validate(e, context);
            }
        }

        internal static void Validate(this EmailRestriction source, Exceptions.ValidationException e, Dal.Context context)
        {
            if(!(source.SiteId > 0))
            {
                e.Add("Site Id must be specified");
            }
            if (string.IsNullOrEmpty(source.EmailFilter))
            {
                e.Add("Email Filter must be specified");
            }
        }
    }

}
